<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        /*
            注意: 抽象工厂模式其实只适用于一些复杂的场景, 不是所有场合都推荐使用。

            抽象工厂模式不会直接生成实例, 而是对于产品类簇的创建

            上节课我们对于不同类型的用户给出了不同的pages, 从而一定程度上解决了用户权限的问题.
            但是你仔细想一想, 我们真实的开发过程中, 管理员和用户的区别仅限于看到的页面不同吗? 
            显然不是, 他们会有很多区别, 比如超级管理员可以对于管理员进行编辑和添加, 而普通管理员对于普通用户又可以编辑或者添加, 这些都是真实的业务场景, 所以我们必须要考虑到这些.
            我们是不能像上节课一样, 只搞一个user类, 把所有的方法与属性都写在里面, 因为不同用户用到的方法根本不同.
            所以我们可以借助ES6中的继承特点, 搞一个抽象类User, 把所有类型用户都会有的属性以及方法在这个类里完成, 然后不同类型的用户都创建一个类继承自User, 最后根据需要对于User中的方法进行重写, User中没有的就进行新增, 这样就解决了这个问题, 让代码实现了低耦合.
            最后我们再搞一个getUserAbstract()函数, 传入你想创建的用户类型名称, 这个方法会返回目标类, 你再去new就行了.
        */ 
       class User{
            constructor(name,role,pages){
                this.name = name;
                this.role = role;
                this.pages = pages;
            }

            // 不管什么类型用户, 应该都用得到这个欢迎功能
            welcome(){
                console.log('欢迎回来, 尊敬的'+this.name);
            }

            // 虽然每个类型用户都有dataShow方法, 但是要做的事情是不同的, 所以我们需要子类自己去重写
            dataShow(){
                throw new Error('这是抽象类, 需要你手动实现');
            }
       }

       class SuperAdmin extends User{
            constructor(name,role,pages){
                super(name,'superadmin',['home', 'user-manage','admin-manage'])
            }

            // 增加管理员是超级管理员独有的功能, 所以由SuperAdmin自己实现
            addAdmin(){
                console.log('这个方法可以添加一个管理员');
            }

            dataShow(){
                console.log('这是dataShow方法');
            }
       }

       class Admin extends User{
        constructor(name,role,pages){
                super(name,'superadmin',['home', 'user-manage'])
            }

            // 增加一个普通用户是普通管理员的功能, 所以由Admin类自己实现
            addUser(){
                console.log('这个方法可以添加一个普通用户');
            }

            dataShow(){
                console.log('这是dataShow方法');
            }
       }

        // 根据角色去获得你想要生成的类
       function getUserAbstract(role){
            switch(role){
                case 'user':{
                    return User;
                    break;
                }
                case 'superadmin':{
                    return SuperAdmin;
                    break;
                }
                case 'admin':{
                    return Admin;
                    break;
                }
                default:{
                    throw new Error('no such role as'+role);
                }
            }
       }

       let UserClass = getUserAbstract('superadmin');
       let SuperAdmin1 = new UserClass('mikaisa')
       console.log(SuperAdmin1);
    </script>
</body>
</html>